package com.tju.resource.server.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tju.resource.mapper.TbCmdProdMapper;
import com.tju.resource.mapper.TbCommandMapper;
import com.tju.resource.mapper.TbProdPlanMapper;
import com.tju.resource.model.TbCmdProd;
import com.tju.resource.model.TbCommand;
import com.tju.resource.model.TbOrder;
import com.tju.resource.model.TbProdPlan;
import com.tju.resource.server.SysParamsService;
import com.tju.resource.server.TbCommandService;
import com.tju.resource.server.TbOrderService;
import com.tju.resource.server.TbProdPlanService;
import com.tju.resource.tool.result.Result;
import com.tju.resource.tool.result.ResultEnum;
import com.tju.resource.tool.result.ResultUtil;
import com.tju.resource.tool.tool.ChineseExceptionUtils;
import com.tju.resource.tool.tool.ClientParameters;
import com.tju.resource.tool.tool.EmptyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

@Service
public class TbCommandServiceImpl implements TbCommandService {

    private static int i = 0; //自增
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    @Autowired
    private TbCommandMapper tbCommandMapper;
    @Autowired
    private TbCmdProdMapper tbcmdProdMapper;
    @Autowired
    private SysParamsService paramsServiceService;
    @Autowired
    private TbOrderService tbOrderService;
    @Autowired
    private ChineseExceptionUtils zh_CH;
    @Autowired
    private TbProdPlanService tbProdPlanService;
    @Autowired
    private TbProdPlanMapper TbProdPlanMapper;

    /**
     * 新增指令信息
     *
     * @param command 指令信息
     * @return 结果
     */
    @Override
    @Transactional
    public Result<Object> insertCommand(TbCommand command) {
        try {
            String cmdNumber = command.getCmdNumber(); //指令号
            String createBy = command.getCreateBy();//创建人
            TbOrder tbOrder = tbOrderService.checkOrderNumberUnique(command.getOrderNumber());
            long data = (command.getDelivery().getTime() - sdf.parse(sdf.format(new Date())).getTime()) / (24 * 3600 * 1000);  //算出来距离几天
            long paramsValue = Long.parseLong(paramsServiceService.get("CMD_DELIVERY").getParamsValue());  //拿到你设置多少天交期
            if (data < paramsValue) {
                return ResultUtil.success(ResultEnum.UNKONW_ERROR, "交期时间必须大于指令时间：" + paramsValue + "天");
            }
            if (EmptyUtils.isNotEmpty(checkCommandNumberUnique(cmdNumber))) { //判断不为空进入
                return ResultUtil.error(ResultEnum.UNKONW_ERROR, "指令号重复了：" + cmdNumber);
            }
            if (EmptyUtils.isEmpty(tbOrder)) {
                return ResultUtil.error(ResultEnum.UNKONW_ERROR, "订单号不存在：" + command.getOrderNumber());
            }
            if (EmptyUtils.isEmpty(cmdNumber)) {
                if (EmptyUtils.isNotEmpty(createBy)) {
                    command.setCmdNumber(cmdNumber(createBy));
                } else {
                    return ResultUtil.error(ResultEnum.UNKONW_ERROR, zh_CH.MissingParameters);
                }
            }
            command.setOrderId(tbOrder.getId()); //创建订单id
            command.setCreateTime(new Date());//创建时间
            if (tbCommandMapper.insert(command) > 0) {
                Long[] prodId = command.getProdId();  //拿到生产计划的id
                if (EmptyUtils.isNotEmpty(prodId)) {      //判断不为空进入
                    int prodIdCount = prodId.length;  //生产计划数量
                    int addProdIdCount = 0;  //添加数量
                    TbCmdProd cmd;
                    TbProdPlan tbProdPlanById;
                    for (Long prod : prodId) {  //循环生产计划
                        tbProdPlanById = TbProdPlanMapper.getTbProdPlanById(prod); //查询是否有这个生产计划
                        if (EmptyUtils.isEmpty(tbProdPlanById)) {//该生产计划不为空
                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //回滚
                            return ResultUtil.error(ResultEnum.UNKONW_ERROR, "该订单号:" + tbOrder.getOrderNumber() + "下面没有该生产计划");

                        } else {
                            if (!command.getOrderNumber().equals(tbProdPlanById.getOrderNumber())) { //判断该生产计划的订单号跟悬着的订单号一致
                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //回滚
                                return ResultUtil.error(ResultEnum.UNKONW_ERROR, "该订单号" + command.getOrderNumber() + " 不对应生产计划订单号：" + tbProdPlanById.getOrderNumber());
                            }
                        }
                        cmd = new TbCmdProd();
                        cmd.setCmdId(command.getId());  //添加指令号的id
                        cmd.setProdId(prod);  //添加生产计划的id
                        cmd.setCreateTime(new Date());
                        cmd.setCreateBy(createBy);
                        addProdIdCount = addProdIdCount + tbcmdProdMapper.insert(cmd);  //添加
                        if (prodIdCount == addProdIdCount) {
                            return ResultUtil.success(ResultEnum.SUCCESS, zh_CH.AddedSuccessfully);
                        }
                    }
                } else {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return ResultUtil.error(ResultEnum.UNKONW_ERROR, "没选择生产计划!");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultUtil.error(ResultEnum.UNKONW_ERROR, zh_CH.AddFailed);
    }

    /**
     * 修改指令信息
     *
     * @param command 指令信息
     * @return 结果
     */
    @Override
    @Transactional
    public Result<Object> updateCommand(TbCommand command) {
        try {
            Long id = command.getId();  //拿到修改指令的id
            TbCommand tbCommand = tbCommandMapper.selectById(id); //查询修改指令的指令管理
            TbOrder tbOrder = tbOrderService.checkOrderNumberUnique(command.getOrderNumber()); //根据订单号查询订单信息
            if (EmptyUtils.isEmpty(tbOrder)) { //订单号不存在
                return ResultUtil.error(ResultEnum.UNKONW_ERROR, "订单号不存在：" + command.getOrderNumber());
            }
            if (EmptyUtils.isNotEmpty(tbCommand)) { //判断指令号不等于空
                long data = (command.getDelivery().getTime() - sdf.parse(sdf.format(tbCommand.getCreateTime())).getTime()) / (24 * 3600 * 1000);  //算出来距离几天
                long paramsValue = Long.parseLong(paramsServiceService.get("CMD_DELIVERY").getParamsValue());  //交期
                if (data < paramsValue) {
                    return ResultUtil.success(ResultEnum.UNKONW_ERROR, "交期时间必须大于指令时间：" + paramsValue + "天");
                }
                if (!tbCommand.getCmdNumber().equals(command.getCmdNumber())) {//指令号不一样
                    if (EmptyUtils.isNotEmpty(checkCommandNumberUnique(command.getCmdNumber()))) { //判断不为空进入
                        return ResultUtil.error(ResultEnum.UNKONW_ERROR, "指令号重复了：" + command.getCmdNumber());
                    }
                }
                command.setUpdateTime(new Date()); //修改时间
                command.setOrderId(tbOrder.getId()); //修改的订单号id
                if (tbCommandMapper.updateById(command) > 0) { //修改成功
                    QueryWrapper<TbCmdProd> qw = new QueryWrapper<>();//条件
                    qw.eq("cmd_id", id);
                    List<TbCmdProd> tbCmdProds = tbcmdProdMapper.selectList(qw); //查询之前的
                    for (TbCmdProd tbCmdProd : tbCmdProds) {
                        tbcmdProdMapper.deleteById(tbCmdProd.getId()); //把之前的删除
                    }
                    Long[] prodId = command.getProdId();  //拿到生产计划的id
                    if (EmptyUtils.isNotEmpty(prodId)) {      //判断不为空进入
                        int prodIdCount = prodId.length;  //生产计划数量
                        int addProdIdCount = 0;  //添加数量
                        TbCmdProd cmd;
                        TbProdPlan tbProdPlanById;
                        for (Long prod : prodId) { //循环生产计划
                            tbProdPlanById = TbProdPlanMapper.getTbProdPlanById(prod); //拿到该生产计划
                            if (EmptyUtils.isNotEmpty(tbProdPlanById)) {//该生产计划不为空
                                if (!command.getOrderNumber().equals(tbProdPlanById.getOrderNumber())) { //判断该生产计划的订单号跟悬着的订单号一致
                                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //回滚
                                    return ResultUtil.error(ResultEnum.UNKONW_ERROR, "该订单号" + command.getOrderNumber() + " 不对应生产计划订单号：" + tbProdPlanById.getOrderNumber());
                                }
                            } else {
                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //回滚
                                return ResultUtil.error(ResultEnum.UNKONW_ERROR, "该订单号:" + tbOrder.getOrderNumber() + "下面没有该生产计划");
                            }
                            cmd = new TbCmdProd(); //生成指令跟生产计划对应的对象
                            cmd.setCmdId(id);  //添加指令号的id
                            cmd.setProdId(prod);  //添加生产计划的id
                            cmd.setCreateTime(new Date()); //创建时间
                            cmd.setCreateBy(command.getCreateBy()); //创建人
                            addProdIdCount = addProdIdCount + tbcmdProdMapper.insert(cmd);  //添加光联
                            if (prodIdCount == addProdIdCount) {
                                return ResultUtil.success(ResultEnum.SUCCESS, zh_CH.SuccessfullyModified);
                            }
                        }
                    } else {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return ResultUtil.error(ResultEnum.UNKONW_ERROR, "没选择生产计划!");
                    }
                }
            } else {
                return ResultUtil.error(ResultEnum.UNKONW_ERROR, zh_CH.MissingParameters);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultUtil.error(ResultEnum.UNKONW_ERROR, zh_CH.FailToEdit);
    }

    /**
     * 查询指令信息
     *
     * @param param 指令信息
     * @return 结果
     */
    @Override
    public Result<Object> selectCommandList(ClientParameters param) {
        try {
            Integer pageNum = param.getPage();  //页码
            Integer limit = param.getLimit(); //页数量
            if (EmptyUtils.isNotEmpty(pageNum) && EmptyUtils.isNotEmpty(limit)) {  //不等于空
                Long[] prodId;
                Page<TbCommand> page = new Page<>(pageNum, limit); //分页

                IPage<TbCommand> iPage = tbCommandMapper.selectCommandList(page, param); //分页查询
                for (TbCommand tb : iPage.getRecords()) {  //循环订单号
                    List<TbCmdProd> tbCmdProds = listCmdProdListByCmdId(tb.getId());  //查询到指令号下面的生产计划
                    int size = tbCmdProds.size();
                    prodId = new Long[size];
                    for (int tbCmdProdsIndex = 0; tbCmdProdsIndex < size; tbCmdProdsIndex++) { //循环生产计划
                        prodId[tbCmdProdsIndex] = tbCmdProds.get(tbCmdProdsIndex).getProdId();  //拿到生产计划id
                    }
                    tb.setProdId(prodId); //用订单号算出生产计划数量
                }
                return ResultUtil.success(ResultEnum.SUCCESS, iPage.getRecords(), iPage.getTotal()); //第二个参数 分页查询列表 第三个参数总数
            } else {
                return ResultUtil.error(ResultEnum.UNKONW_ERROR, zh_CH.MissingParameters);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultUtil.error(ResultEnum.UNKONW_ERROR);
    }

    /**
     * 删除指令信息
     *
     * @param command 指令信息
     * @return 结果
     */
    @Override
    @Transactional
    public Result<Object> deleteCommand(TbCommand command) {
        try {
            int deleteIdCount = 0; //删除数量
            Long id = command.getId();  //删除id
            if (EmptyUtils.isNotEmpty(id)) { //不等于空
                List<TbCmdProd> tbCmdProds = listCmdProdListByCmdId(id);
                //循环生产计划
                for (TbCmdProd tbCmdProd : tbCmdProds)
                    deleteIdCount = deleteIdCount + tbcmdProdMapper.deleteById(tbCmdProd.getId());
                if (tbCmdProds.size() == deleteIdCount && tbCommandMapper.deleteById(command.getId()) > 0) {  //判断删除数量跟原始
                    return ResultUtil.success(ResultEnum.SUCCESS, zh_CH.SuccessfullyDeleted);
                }
            } else {
                return ResultUtil.error(ResultEnum.UNKONW_ERROR, zh_CH.MissingParameters);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultUtil.success(ResultEnum.SUCCESS, zh_CH.FailedToDelete);
    }

    /**
     * 根据订单查询
     *
     * @param orderNumber
     * @return
     */
    @Override
    public Result<Object> getOrderNumber(String orderNumber) {
        try {
            if (EmptyUtils.isNotEmpty(orderNumber)) {
                TbOrder tbOrder = tbOrderService.checkOrderNumberUnique(orderNumber); //根据订单号查询
                List<TbProdPlan> byOR;
                if (EmptyUtils.isNotEmpty(tbOrder)) {
                    byOR = new CopyOnWriteArrayList<>(tbProdPlanService.getByOR(tbOrder.getId()));  //拿到上产计划 解决并发
                    List<TbCommand> tbCommandList = tbCommandMapper.getTbCommandList(orderNumber, null); //拿到已用的生产计划
                    for (TbProdPlan tbProdPlan : byOR) {  //对比
                        tbProdPlan.setOrderNumber(orderNumber);//订单号
                        for (TbCommand tbCommand : tbCommandList) {  //循环
                            tbProdPlan.setCmdNumber(tbCommand.getCmdNumber()); //指令号
                            for (int tbCmdProdListIndex = 0; tbCmdProdListIndex < tbCommand.getTbCmdProdList().size(); tbCmdProdListIndex++) { //对比
                                if (tbProdPlan.getId().equals(tbCommand.getTbCmdProdList().get(tbCmdProdListIndex).getProdId())) { //对比
                                    tbProdPlan.setSelected(true); //选中
                                }
                            }
                        }
                    }
                    return ResultUtil.success(ResultEnum.SUCCESS, byOR); //成功！
                } else {
                    return ResultUtil.error(ResultEnum.UNKONW_ERROR, "没有该订单号!");
                }
            } else {
                return ResultUtil.error(ResultEnum.UNKONW_ERROR, zh_CH.MissingParameters);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultUtil.error(ResultEnum.UNKONW_ERROR);
    }

    /**
     * 生产指令号
     *
     * @param param
     * @return
     */
    @Override
    public Result<Object> productionCmdNumber(ClientParameters param) {
        try {
            String one = param.getOne(); //参数
            if (EmptyUtils.isNotEmpty(one)) {
                return ResultUtil.success(ResultEnum.SUCCESS, cmdNumber(one));
            } else {
                return ResultUtil.error(ResultEnum.UNKONW_ERROR, zh_CH.MissingParameters);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultUtil.error(ResultEnum.UNKONW_ERROR);
    }

    /**
     * 生产指令号
     */
    public String cmdNumber(String createBy) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmm");  //转换
        i = i + 1;  //自增
        return createBy + formatter.format(new Date()) + i;
    }

    /**
     * 根据订单id查询
     */
    @Override
    public List<TbCommand> getByOrderId(Long orderId) {
        QueryWrapper<TbCommand> query = new QueryWrapper<>();
        query.eq("order_id", orderId);
        return tbCommandMapper.selectList(query);
    }

    /**
     * 指令号唯一
     */
    public TbCommand checkCommandNumberUnique(String cmdNumber) {
        QueryWrapper<TbCommand> qw = new QueryWrapper<>();
        qw.eq("cmd_number", cmdNumber);
        return tbCommandMapper.selectOne(qw);
    }

    /**
     * 根据id查询下面的计划
     *
     * @param cmdId
     * @return
     */
    public List<TbCmdProd> listCmdProdListByCmdId(Long cmdId) {
        QueryWrapper<TbCmdProd> qw = new QueryWrapper<>();
        qw.eq("cmd_id", cmdId);
        return tbcmdProdMapper.selectList(qw);
    }
}
